<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- 
      监听：
        作用：
          监听某个数据发生变化之后去做一些副作用操作，比如 调用接口、操作DOM...

        基础语法:
          watch: {
            key: value
          }
              key   - 是要监听的数据，支持路径的写法
              value - 是一个处理函数
                      1. 会收到 newVal 与 oldVal 两个参数

        高级语法：
          watch: {
            key: {
              handler(newVal, oldVal) {
              },
              deep: true,
              immediate: true,
              flush: 'pre' | 'post' | 'sync'
            }
          }
              handler     - 原本的处理函数
              deep        - 是否要开启深度监听，默认为 false
              immediate   - 是否要立即执行一次处理函数，默认为 false
              flush       - 控制处理函数的执行时机，默认是 pre
                            pre  - 要真实DOM更新之前触发
                            post - 真实DOM更新之后触发
                            sync - 立即触发，不等待。（一般不使用，有性能问题）
     -->

    <div id="app">
      <input type="text" placeholder="请输入问题" v-model="question" />

      <p>{{ answer }}</p>

      <img v-show="imgUrl" :src="imgUrl" alt="" width="200" height="200" />

      <hr />

      <button @click="person.name += '~'">{{ person.name }}</button>
      <button @click="person.age++">{{ person.age }}</button>

      <hr />

      <button id="box" @click="address.area = '南山区'">
        {{ address.province }} - {{ address.city }} - {{ address.area }}
      </button>

      <button @click="fn1">点击，修改 address</button>
    </div>

    <script src="../lib/vue3.js"></script>

    <script>
      Vue.createApp({
        data() {
          return {
            // 问题
            question: "",
            // 答案
            answer: "...",
            // 答案图片
            imgUrl: "",

            person: {
              name: "张三",
              age: 18,
            },

            address: {
              province: "广东省",
              city: "深圳市",
              area: "宝安区",
            },
          };
        },

        watch: {
          question(newVal, oldVal) {
            if (newVal.includes("?")) {
              // 调用后端接口
              this.getAnswer();
            }
            // console.log("newVal", newVal);
            // console.log("oldVal", oldVal);
          },

          "person.age"(newVal, oldVal) {
            console.log("age", newVal, oldVal);
          },

          "person.name": {
            handler(newVal, oldVal) {
              console.log("person.name", newVal, "-", oldVal);
            },

            immediate: true, // 默认触发一次
          },

          /**
           * 直接修改 address 中某个属性，无法触发下面的监听回调
           *    address.area = '南山区'
           * 直接将整个 address 重新赋值的话，可以触发
           *    address = { province: '广东省', city: '深圳市', area: '南山区' }
           */
          // address() {
          //   console.log("address");
          // },

          address: {
            handler() {
              console.log(document.getElementById("box").innerHTML);
              console.log("address");
            },

            deep: true, // 深度监听

            flush: "sync", // 处理函数的执行时机
          },
        },

        methods: {
          fn1() {
            // 下面代码会引起 address 的监听处理函数执行的次数几次？
            //    1. 如果 配置的 flush 不是 sync      1次
            //    2. 如果 配置的 flush 是   sync      2次
            this.address.city = "广州市";
            this.address.area = "白云区";
          },

          getAnswer() {
            this.answer = "Thinking...";
            fetch("https://yesno.wtf/api")
              .then((response) => response.json())
              .then((result) => {
                console.log("result", result);
                this.answer = result.answer;
                this.imgUrl = result.image;
              })
              .catch(() => {
                this.answer = "Error, 接口错误";
              });
          },
        },
      }).mount("#app");
    </script>
  </body>
</html>
